import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:syn_4s/core/extension/build_context_extension.dart';
import 'package:syn_4s/core/extension/int_extension.dart';
import 'package:syn_4s/core/model/alert_model.dart';
import 'package:syn_4s/core/model/asset_model.dart';
import 'package:syn_4s/core/model/helmet_model.dart';
import 'package:syn_4s/core/model/lock_model.dart';
import 'package:syn_4s/core/model/main_model.dart';
import 'package:syn_4s/core/model/permit_to_work_model.dart';
import 'package:syn_4s/core/model/project_model.dart';
import 'package:syn_4s/core/model/safety_training_model.dart';
import 'package:syn_4s/core/model/short_model.dart';
import 'package:syn_4s/core/model/watch_model.dart';
import 'package:syn_4s/core/model/weather_model.dart';
import 'package:syn_4s/core/services/combo_request.dart';
import 'package:syn_4s/core/services/main_request.dart';
import 'package:syn_4s/core/utils/dialog_utils.dart';
import 'package:syn_4s/ui/widgets/custom_ui.dart';

import '../constants/sp_key.dart';
import '../constants/tag_code.dart';
import '../model/base/api_result_data.dart';
import '../model/gas_model.dart';
import '../model/map_all_device_model.dart';
import '../model/un_safe_act_model.dart';
import '../services/config.dart';
import '../services/google_map_request.dart';
import '../services/tag_request.dart';
import '../utils/location_per_utils.dart';
import '../utils/sp_utils.dart';
import '../utils/toast_utils.dart';

typedef GetShortCallback = void Function(List<ShortModel> data);

class MainViewModel extends GetxController {
  bool isShow = true;
  var isSafetyScrollable = true.obs;
  var isGasScrollable = true.obs;
  var isWatchScrollable = true.obs;
  var isLockScrollable = true.obs;
  var is360PlantScrollable = true.obs;
  var isAlertScrollable = true.obs;
  var isUnsafeScrollable = true.obs;
  final RxList<Dwss> permitToWorks = <Dwss>[].obs;
  final RxList<Vr> vrs = <Vr>[].obs;
  final RxList<Weather?> weathers = <Weather?>[].obs;
  final RxList<GasMonitoring> gasMonitoring = <GasMonitoring>[].obs;
  final RxList<Watch> watches = <Watch>[].obs;
  final RxList<LockModel> locks = <LockModel>[].obs;
  var asset = AssetModel().obs;
  var helmets = HelmetModel().obs;
  final RxList<Alert> alerts = <Alert>[].obs;
  final RxList<UnSafeActModel> unSafeActs = <UnSafeActModel>[].obs;

  var gasKeyword = "".obs;
  var projName = "".obs;
  String projCode = "";
  var alertName = "".obs;
  String alertCode = "";
  List<String> tagCodes = [];
  FocusNode myFocusNode = FocusNode();

  var gpsDevices = "".obs;
  List<String> deviceTagCodes =
      <String>["SynEleclock", "SynHelmet", "SynWatch"].obs;
  var location = "".obs;
  late final RxList<MapAllDeviceModel> deviceList = <MapAllDeviceModel>[].obs;
  Set<Marker> marker = <Marker>{}.obs;

  initData(BuildContext context) {
    SharedPreferences.getInstance().then((value) {
      projName.value = value.getString(keyProjName) ?? "";
      projCode = value.getString(keyProjCode) ?? "";
      String? spAlert = value.getString(keyAlertName);
      spAlert =
          (spAlert == null || spAlert.isEmpty) ? context.l10n.all : spAlert;
      alertName.value = spAlert;
      alertCode = value.getString(keyAlertCode) ?? "";
      tagCodes.addAll((value.getString(keyTagCode) ?? "").split(","));
      getDash();
      Timer.periodic(const Duration(milliseconds: 600000), (timer) {
        print("isShow：$isShow");
        if (isShow) {
          getDash();
        }
      });
    });
  }

  getDash({RefreshController? controller}) {
    for (var value in tagCodes) {
      getData(projCode, value);
    }
    getWeather(controller: controller);
  }

  getData(String projCode, String synProj) {
    if (synProj == codeGas) {
      getGasMonitoring();
    } else if (synProj == codeAlert) {
      getAlert(alertCode);
    } else {
      MainRequest.getData(projCode: projCode, synProj: synProj).then((value) {
        ApiResultData<MainModel> result =
            ApiResultData.fromJson(value, MainModel.fromJson);
        if (result.status != HttpConfig.success) {
          return;
        }
        if (result.data == null) {
          return;
        }
        if (synProj == codePermitToWork) {
          if (result.data?.dwss?.isNotEmpty ?? false) {
            permitToWorks.clear();
            permitToWorks.addAll(result.data?.dwss ?? []);
          }
        } else if (synProj == codeSafetyTraining) {
          vrs.clear();
          vrs.addAll(result.data?.vr ?? []);
        } else if (synProj == codeWatch) {
          watches.clear();
          watches.addAll(result.data?.watch ?? []);
        } else if (synProj == codeLock) {
          locks.clear();
          locks.addAll(result.data?.eleclock ?? []);
        } else if (synProj == codeTracking) {
          asset.value = result.data?.asset ?? AssetModel();
        } else if (synProj == code360) {
          helmets.value = result.data?.helmet ?? HelmetModel();
        } else if (synProj == codeUnSafeAct) {
          unSafeActs.clear();
          unSafeActs.addAll(result.data?.aIConstSite ?? []);
        }
      });
    }
  }

  getWeather({RefreshController? controller}) {
    MainRequest.getData(projCode: projCode, synProj: codeWeather).then((value) {
      ApiResultData<WeatherModel> apiResultData =
          ApiResultData<WeatherModel>.fromJson(value, WeatherModel.fromJson);
      controller?.refreshCompleted(resetFooterState: true);
      if (apiResultData.status != HttpConfig.success) {
        return;
      }
      if (apiResultData.data != null &&
          (apiResultData.data?.weather?.isNotEmpty ?? false)) {
        weathers.clear();
        weathers.addAll(apiResultData.data?.weather ?? []);
      }
    }).catchError((err) {
      controller?.refreshCompleted(resetFooterState: true);
    });
  }

  getGasMonitoring() {
    MainRequest.getData(
            projCode: projCode, synProj: codeGas, keyWord: gasKeyword.value)
        .then((value) {
      ApiResultData<GasModel> apiResultData =
          ApiResultData<GasModel>.fromJson(value, GasModel.fromJson);
      if (apiResultData.status != HttpConfig.success) {
        return;
      }
      if (apiResultData.data != null &&
          (apiResultData.data?.envtal?.isNotEmpty ?? false)) {
        gasMonitoring.clear();
        gasMonitoring.addAll(apiResultData.data?.envtal ?? []);
      }
    });
  }

  getAlert(String keyWord) {
    MainRequest.getData(
            projCode: projCode, synProj: codeAlert, keyWord: keyWord)
        .then((value) {
      ApiResultData<AlertModel> apiResultData =
          ApiResultData<AlertModel>.fromJson(value, AlertModel.fromJson);
      if (apiResultData.status != HttpConfig.success) {
        return;
      }
      if (apiResultData.data != null &&
          (apiResultData.data?.alert?.isNotEmpty ?? false)) {
        alerts.clear();
        alerts.addAll(apiResultData.data?.alert ?? []);
      }
    });
  }

  getProjects(BuildContext context, GlobalKey globalKey) {
    DialogUtils.loading(context);
    MainRequest.getProjects("projs").then((value) {
      DialogUtils.closeDialog(context);
      if (value.status != HttpConfig.success) {
        ToastUtils.showToast(value.message ?? "");
        return;
      }
      List<ProjectModel> data = value.data ?? [];
      for (var model in data) {
        if (model.code == projCode) {
          model.isSelect = true;
        }
      }
      showProjectMenu(context, data, globalKey).then((selModel) {
        if (selModel != null && projCode != selModel.code) {
          changeTag(context, selModel);
        }
      });
    }).catchError((err) {
      DialogUtils.closeDialog(context);
      ToastUtils.showNetError(context);
    });
  }

  changeTag(BuildContext context, ProjectModel model) {
    DialogUtils.loading(context);
    TagRequest.getTags().then((value) {
      DialogUtils.closeDialog(context);
      if (value.status != HttpConfig.success) {
        ToastUtils.showToast(value.message ?? "");
        return;
      }
      projCode = model.code ?? "";
      projName.value = model.name ?? "";

      SPUtils.set(keyProjId, model.id ?? "");
      SPUtils.set(keyProjName, projName.value);
      SPUtils.set(keyProjCode, projCode);
      String? codes = value.data
          ?.tags?.map((tag) => tag.code)
          .where((code) =>
              code != null &&
              code.isNotEmpty &&
              code != codeStatus &&
              code != codeRealLocation &&
              code != codeTowerCrane &&
              code != codeSurveillance)
          .join(',');
      SPUtils.set(keyTagCode, codes ?? "");
      SPUtils.set(
          keyTag, jsonEncode(value.data?.tags?.map((v) => v.toJson()).toList()));
      tagCodes.addAll((codes ?? "").split(","));
      getDash();
    }).catchError((err) {
      print(err);
      DialogUtils.closeDialog(context);
      ToastUtils.showNetError(context);
    });
  }

  getAlertTypes(
    BuildContext context,
    GlobalKey globalKey,
  ) {
    getCombos(context, globalKey, typeKey: "synProjAlarms", callback: (data) {
      DialogUtils.alertMultiListDialog(context, data, selId: alertCode,
          callback: (value) {
        bool isAll = true;
        String codes = "";
        String names = "";
        for (var data in value) {
          if (data.isSelect ?? false) {
            codes += "${data.code ?? ""},";
            names += "${data.name ?? ""},";
          } else {
            isAll = false;
          }
        }
        if (codes.isEmpty) {
          ToastUtils.showToast(context.l10n.p_sel_alert_type);
          return;
        }
        DialogUtils.closeDialog(context);
        if (isAll) {
          alertCode = "";
          alertName.value = context.l10n.all;
          SPUtils.set(keyAlertName, "");
        } else {
          alertCode = codes.substring(0, codes.length - 1);
          alertName.value = names.substring(0, names.length - 1);
          SPUtils.set(keyAlertName, alertName.value);
        }
        SPUtils.set(keyAlertCode, alertCode);
        getAlert(alertCode);
      });
    });
  }

  getLocation(BuildContext context) {
    getLocationInfo(context).then((loction) {
      location.value = loction!.first!.subLocality!;
    });
  }

  getGpsDevice(
    BuildContext context,
    GlobalKey globalKey,
  ) {
    getCombos(context, globalKey, typeKey: "synProjMaps", callback: (data) {
      for (var model in data) {
        for (var tag in deviceTagCodes) {
          if (tag == model.code) {
            model.isSelect = true;
          }
        }
      }
      showShortMenu(context, data, globalKey, width: 180.px).then((value) {
        if (value != null && projCode != value.code) {
          if (value.isSelect == true) {
            value.isSelect = false;
            deviceTagCodes.remove(value.code);
          } else {
            value.isSelect = true;
            deviceTagCodes.add(value!.code!);
          }
          getAllDevice();
        }
      });
    });
  }

  void getAllDevice() {
    GoogleMapRequest.getAllDevice(deviceTagCodes.toString()).then((result) {
      // setState(() {
      if (result.status != HttpConfig.success) {
        ToastUtils.showToast(result.message ?? "");
        return;
      }
      deviceList.addAll(result!.data!);
    }).catchError((error) {
      print(error.toString());
    });
  }

  getCombos(BuildContext context, GlobalKey globalKey,
      {required String typeKey, required GetShortCallback callback}) {
    DialogUtils.loading(context);
    ComboRequest.getCombo(typeKey).then((value) {
      DialogUtils.closeDialog(context);
      if (value.status != HttpConfig.success) {
        ToastUtils.showToast(value.message ?? "");
        return;
      }
      List<ShortModel> data = value.data ?? [];
      callback(data);
    }).catchError((err) {
      DialogUtils.closeDialog(context);
      ToastUtils.showNetError(context);
    });
  }
}
